Memcoin Β· UTXO Temperature Β· design & architecture

Storage cools.
Spendability never does.

Without intervention, the UTXO set grows without bound β€” every output, once created, occupies node storage indefinitely regardless of value or age. The temperature system migrates unspent outputs through progressively compressed storage tiers as they age, without ever affecting whether they can be spent.

Overview

Internal to the node.
Invisible to the network.

The temperature system does not modify the block format, transaction format, or network protocol. All nodes remain equal peers. The lifecycle is governed by two layers of rules: consensus rules, which every node enforces unconditionally when validating a block, and node configuration parameters, which govern local storage behavior and can be adjusted by operators without a protocol fork.

Consensus rules

Enforced by every node.

The demotion schedule and Normal-tier migration logic are consensus β€” a block that omits a required demotion, or processes one incorrectly, is invalid.

Node configuration

Adjustable, no fork required.

Protection period, ice index depth, and pruning behavior are local storage decisions. Operators tune them freely; the network never sees the difference.

Transaction types

Two output types.
One temperature system.

Memcoin has two output types relevant to temperature. They're treated identically in every storage tier, with one deliberate exception.

P2PKH

Standard outputs.

Spendable by the holder of a matching private key. Created by standard transactions and by TX2. The temperature clock starts at the block where the output confirmed.

CLTV+P2PKH

Time-locked outputs.

Created exclusively by TX1, encoding an unlockHeight enforced by OP_CHECKLOCKTIMEVERIFY. TX1 requires exactly one P2PKH input (R0), a locked value capped at 1 MEM (R5), and a locktime within Β±30 blocks of a 432-block lock period (R2). Spent exclusively by TX2, which accepts only CLTV+P2PKH inputs (R7) and produces only P2PKH outputs (R10b) β€” locked outputs never chain or nest; the payment graph stays flat.

The one exception

For CLTV+P2PKH outputs, the temperature clock starts at unlockHeight, not confirmation height. A locked payment doesn't get penalized for time it was never allowed to spend in the first place.

The lifecycle

Forward-only.
No promotion back.

A UTXO moves through three storage tiers as it ages. The path runs one direction only.

In-memory Β· instant

Normal

Standard chainstate database lookup. Every newly confirmed output enters here and stays until its temperature reaches zero.

β†’
Compressed disk index

Cold

A single record per address, shared across every output at that address. Spendable without reading any historical block.

β†’
Per-address height list

Ice

Only block heights remain on file. Spending reads those blocks and reconstructs the output's data on demand.

Temperature & demotion

A linear function
of value and age.

Temperature determines when a UTXO moves between tiers β€” it decays every block, at a rate fixed by consensus.

T1
COOLING_RATE = 2000 Κ™ / block β€” combined with the 10 kbit output floor, this guarantees every non-coinbase output spends at least 5 blocks in Normal before any demotion is possible.
T2
temperature(h) = value βˆ’ COOLING_RATE Γ— (h βˆ’ heightAnchor) β€” heightAnchor is confirmation height for P2PKH, unlock height for CLTV+P2PKH.
T3
demotionBlock = heightAnchor + floor(value / COOLING_RATE) + 1 β€” the block at which a Normal-tier UTXO demotes to Cold.
T4
iceDemotionBlock = coldBlock + protectionPeriod + floor(value / COOLING_RATE) + 1 — Cold→Ice cooling is symmetric with the Normal lifetime; protection period sits between them.
T5
protectionPeriod β€” node configuration, default 12,960 blocks (~90 days). Operators may reduce it under storage pressure. Does not affect consensus.

T1–T3 are consensus rules Β· T4–T5 are node configuration

Tier by tier

What each tier
actually stores.

NORMAL
N1
Every confirmed output enters Normal at confirmation; a demotion schedule entry is written, indexed by demotionBlock.
N2
At the start of each block, the node migrates all UTXOs scheduled for demotion before processing any transactions in that block.
N3
Spending a Normal UTXO follows the standard validation path β€” no temperature logic intervenes.
N4
Coinbase outputs use heightAnchor = confirmHeight. The 7 MEM reward floor guarantees maturity (100 blocks) before demotion. CLTV+P2PKH can never appear in coinbase β€” TX1 requires a P2PKH input.
COLD
C1
On demotion, all fields needed for validation are copied directly from the existing coin record β€” no historical block read required.
C2
Outputs at the same address share one record. P2PKH keys on the full scriptPubKey; CLTV+P2PKH keys on the pubkey hash, since TX2's scriptSig alone can't reconstruct the full locking script.
C3
Spending a Cold UTXO reads the cold index directly β€” still no historical block access.
C4
Demoted to Ice at iceDemotionBlock; the cold record is removed and a minimal height entry written to the ice index.
ICE
I1
One record per public key hash: a minHeight fallback anchor plus a delta-encoded list of block heights holding unspent outputs.
I2
Spending triggers an Ice Rebuild β€” the node reads the listed blocks, locates the output, and reconstructs it in memory. Stale height entries are pruned during rebuild.
I3
ice_height_list_max β€” default 36 entries per address; oldest evicted beyond that, with minHeight as fallback. Not a consensus rule.
I4
Nodes lacking the data request it via utxofall. Pruned nodes may disable the ice index entirely with pruned_no_ice=1 and still handle Ice spends correctly.
Normal-tier lifetime (2,000 Κ™/block)
ValueBlocksβ‰ˆ time
10 kbit (min)5~50 min
100 kbit50~8 hours
1 mbit500~3.5 days
1 MEM50,000~347 days
1 MEM output Β· total time to Ice
PhaseBlocksβ‰ˆ time
Normal cooling50,000~347 days
Cold protection12,960~90 days
Cold cooling50,000~347 days
Total to Ice112,960~784 days
Storage per UTXO
TierStorageLookup
Normal~115 Κ™in-memory, O(1)
Cold~75 Κ™disk key read, no block access
Ice~4 Κ™block read and rebuild
utxofall protocol

Point-to-point.
Never broadcast.

Whether a node retains full block history, has pruned, or has disabled the ice index is an internal detail β€” invisible to the network. Every node can send and answer utxofall messages.

U1
All nodes are equal peers at the network layer. Internal storage choices don't change how a node behaves externally.
U2
A node needing UTXO data it can't resolve locally sends UTXO_REQUEST to the node that propagated the spending transaction or block β€” that node already validated it, so it's guaranteed to have the data.
U3
The request is point-to-point. It is not broadcast to the network.
U4
UTXO_REQUEST carries the outpoint (txid + vout). UTXO_RESPONSE carries the outpoint plus value and scriptPubKey. No other data is exchanged.
Exchange
β†’ UTXO_REQUEST txid, vout
← UTXO_RESPONSE txid, vout, value, scriptPubKey
Reorg handling

Two indexes.
No dedicated undo log.

G1
The cold index maintains two reorg indexes — H records which UTXOs entered Cold at each height; X records which moved Cold→Ice at each height, with their complete data.
G2
Both indexes are retained for REORG_BUFFER blocks, then pruned β€” enough to reverse any reorganisation the network will accept in practice.
G3
REORG_BUFFER = 432 blocks (~3 days) β€” hardcoded, not operator-configurable.
G4
The ice index keeps no reorg index of its own. Reorg operations on Ice-tier UTXOs run entirely through the cold index's X entries.
Design rationale

Why it's built
this way.

Why does CLTV use unlockHeight as the temperature anchor?

A CLTV+P2PKH output can't be spent before its locktime expires β€” enforced at consensus. Anchoring on confirmation height would penalize the holder for time the output was legally unspendable. Anchoring on unlock height means the clock starts only once the output becomes accessible, and a TX1 output and a standard output of equal value created at the same effective moment cool at the same rate.

Why per-address storage in Cold, not per-UTXO?

The scriptPubKey β€” the dominant fixed cost β€” is stored once per address rather than once per UTXO. Addresses with many outputs compress significantly; addresses with a single output cost the same as per-UTXO storage would, so there's no downside in the common case.

Why does Cold avoid block reads entirely?

Everything needed for future validation β€” value, scriptPubKey, coinbase flag, block height β€” is copied from the chainstate record at the moment of demotion. Block reads are deferred entirely to Ice, where storage is already minimal and a rebuild is expected to be rare.

Why is utxofall point-to-point rather than broadcast?

Any node that propagated a transaction or block already validated it β€” which means it already resolved every input, including Ice UTXOs. It's guaranteed to hold the data. Broadcasting would reach nodes that may not, wasting bandwidth for no benefit.

Why no dedicated undo system for reorgs?

The H and X indexes already record exactly which UTXOs changed tier and what their data was, for the most recent REORG_BUFFER blocks. Reversing a tier transition is a direct lookup β€” no separate undo file or log needed, since the network won't accept a deeper reorg in practice.

The guarantee

Every UTXO remains spendable at all times. The temperature system never deletes an output β€” migration between tiers is a storage optimisation, not a hold on funds. Cold and Ice differ only in how quickly a node reconstructs the data; with 10-minute blocks, that reconstruction never affects confirmation in practice. Consensus enforces only the demotion schedule and Normal-tier migration β€” Cold and Ice are internal to each node. Nothing about the block format, transaction format, or peer-to-peer protocol changes, apart from the two new point-to-point utxofall messages.